#include "MOTOR.h"

/**
 * 四相步进电机工作方式:
 * 四相步进电机有单四拍(A-B-C-D);扭矩小，功耗小，但震动大。
 * 双四拍(AB-BC-CD-DA);扭矩较大，功耗也大，震动小。
 * 八拍(B-BC-C-CD-D-DA-A-AB);步距角小，输出更平滑。
 */
const uint8_t STEPPER_VALUE_TABLE[8][4] = {
    {0, 1, 0, 0}, // B
    {0, 1, 1, 0}, // BC
    {0, 0, 1, 0}, // C
    {0, 0, 1, 1}, // CD
    {0, 0, 0, 1}, // D
    {1, 0, 0, 1}, // DA
    {1, 0, 0, 0}, // A
    {1, 1, 0, 0}, // AB
};

uint8_t STEPPER_INDEX = 7; // 这里初始位置是AB; (+1位置)->B,(-1位置)->A

void STEPPER_MOTOR_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 总线时钟
    GPIO_InitStructure.GPIO_Pin = STEPPER_MOTOR_A_PIN | STEPPER_MOTOR_B_PIN | STEPPER_MOTOR_C_PIN | STEPPER_MOTOR_D_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(STEPPER_MOTOR_PORT, &GPIO_InitStructure);
    GPIO_SetBits(STEPPER_MOTOR_PORT, STEPPER_MOTOR_A_PIN | STEPPER_MOTOR_B_PIN); // AB
    STEPPER_MOTOR_OFF();
}

void STEPPER_MOTOR_OFF(void)
{
    GPIO_ResetBits(STEPPER_MOTOR_PORT, STEPPER_MOTOR_A_PIN | STEPPER_MOTOR_B_PIN | STEPPER_MOTOR_C_PIN | STEPPER_MOTOR_D_PIN);
}

/**
 * @brief [转子]单步运行
 * @param StepIndex : 第几步[0~7]
 * @param Speed : 延时ms
 * @attention 节拍有先后顺序;只能在当前位置前进或者后退
 */
void STEPPER_MOTOR_Beat(uint8_t StepIndex, uint8_t Speed)
{
    GPIO_WriteBit(STEPPER_MOTOR_PORT, STEPPER_MOTOR_A_PIN, (BitAction)STEPPER_VALUE_TABLE[StepIndex][0]);
    GPIO_WriteBit(STEPPER_MOTOR_PORT, STEPPER_MOTOR_B_PIN, (BitAction)STEPPER_VALUE_TABLE[StepIndex][1]);
    GPIO_WriteBit(STEPPER_MOTOR_PORT, STEPPER_MOTOR_C_PIN, (BitAction)STEPPER_VALUE_TABLE[StepIndex][2]);
    GPIO_WriteBit(STEPPER_MOTOR_PORT, STEPPER_MOTOR_D_PIN, (BitAction)STEPPER_VALUE_TABLE[StepIndex][3]);
    delay_ms(Speed); //
    STEPPER_MOTOR_OFF();
}

/**
 * @brief [转子]按步数运行
 * @param Direction 1:顺时针 ; 0:逆时针
 * @param Steps : 步数;
 */
void STEPPER_MOTOR_Steps(uint8_t Direction, uint16_t Steps, uint8_t Speed)
{
    uint16_t i = 0;
    for (i = 0; i < Steps; i++)
    {
        if (Direction)
        {
            // B->BC->C->CD->D->DA->A->AB
            STEPPER_INDEX++; // 前进
            STEPPER_INDEX = (STEPPER_INDEX % 8);
        }
        else
        {
            // A->AD->D->DC->C->CB->B->BA
            STEPPER_INDEX = (STEPPER_INDEX > 0) ? (STEPPER_INDEX - 1) : (7); // 后退
        }
        STEPPER_MOTOR_Beat(STEPPER_INDEX, Speed);
        printf("Step=%d STEPPER_INDEX=%d  \r\n", i, STEPPER_INDEX);
    }
}
/**
 * @note 28BYJ—48:(步进电机|永磁式|减速型|四相八拍) 减速比:64
 * @note [转子]步进角度=360/(4相*8拍*2)=5.625;[输出轴]步进角度参数=(5.625/64)
 * @note 理论上[输出轴]转一圈需要4096步; 4076(减小误差)
 */
void STEPPER_MOTOR_Rounds(uint8_t Direction, uint16_t Rounds, uint8_t Speed)
{
    STEPPER_MOTOR_Steps(Direction, 4076 * Rounds, Speed);
}
